<?php
/*
Copyright (C) 2009 de Flotte Maxence

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
?>
<?php
/**
 * Open, generate view
 */
class ZzView {
	
	private $view;
	private $dom;
	private $arrayVar;
	private $xPath;
	
	public function __construct($view,$array) {
		$this->view = $view;
		$this->dom = new DOMDocument();
		$this->dom->load('./ZzView/'.$view.'.zzv');
		$this->xPath = new DOMXPath($this->dom);
		$this->arrayVar = $array;
	}
/**
 * Generate a view
 */
	private function gen() {
		$this->dom;
		$listForeach = $this->xPath->query('//*[@foreach]');
		for($i=0; $i<$listForeach->length; $i++) {
			$attribute = $listForeach->item($i)->getAttribute('foreach');
			$node = new DOMElement('php','foreach('.$this->transformForeachAttribute($attribute).') {');
			$this->insertNode($node,$listForeach->item($i),'before');
			$listForeach->item($i)->removeAttribute('foreach');
			$this->insertNode(new DOMElement('php','}'),$listForeach->item($i),'after');
		}
		
		$listIf = $this->xPath->query('//*[@if]');
		for($i=0; $i<$listIf->length; $i++) {
			$attribute = $listIf->item($i)->getAttribute('if');
			$node = new DOMElement('php','if('.$this->transformIfAttribute($attribute).') {');
			$this->insertNode($node,$listIf->item($i),'before');
			$listIf->item($i)->removeAttribute('if');
			$this->insertNode(new DOMElement('php','}'),$listIf->item($i),'after');
		}
		$gen = preg_replace('!<\?.*\?>!','',$this->dom->saveXML($this->dom->getElementsByTagName('view')->item(0)));
		$gen = preg_replace('!\{\*.*\*\}!U','',$gen);
		$gen = preg_replace('!</?view>!U','',$gen);
		$gen = preg_replace_callback('!\{(\$|@)(.*)\}!U', 'ZzView::translateEcho',$gen);
		$gen = str_replace(array('<php>','</php>'),array('<?php ',' ?>'),$gen);
		
		file_put_contents('./ZzView/gen/'.$this->view.'.php','<?php class ZzV_'.$this->view.' {
	function get($arrayVar) { ?>
		'.$gen.'<?php
	}
} ?>');
	}
/**
 * Transform attribute if
 * @param string $attribute
 */
	private function transformIfAttribute($attribute) {
		return $attribute = ZzView::translateVar($attribute);
	}
/**
 * Transform attribute foreach
 * @param string $attribute
 */
	private function transformForeachAttribute($attribute) {
		$asAttribute = str_replace('$','@',preg_replace_callback('!array(.)!',create_function('$var','return strtolower($var[1]);'),$attribute));
		return $attribute = ZzView::translateVar($attribute).' as '.ZzView::translateVar($asAttribute);
	}
/**
 * Transform {$something} to echo instruction
 * @param string $var
 */
	static function translateEcho($var) {
		return '<?php echo '.ZzView::translateVar($var[1].$var[2]).'; ?>';
	}
/**
 * Transform variables and referances ($ and @) to correct php variables
 * @param string $var
 */
	static  function translateVar($var) {
		$var = preg_replace('!\$(.*)!','\$arrayVar[\'$1\']',$var);
		$var = preg_replace('!\@(.*)!','\$$1',$var);
		return $var;
	}
/**
 * Open the gen file
 * @return The html code
 */
	public function open($reGen = false) {
		if(!file_exists('./ZzView/gen/'.$this->view.'.php') or $reGen)
			$this->gen();
		$class = 'ZzV_'.$this->view;
		$obj = new $class();
		ob_start();
			$obj->get($this->arrayVar);
			$gen = ob_get_contents();
		ob_end_clean();
		return $gen;
	}
/**
 * Show the gen file
 */
	public function show($reGen = false) {
		echo $this->open($reGen);
	}
/**
 * Insert a node on a dom document before/after/inside-of an other
 * From php.net :: http://www.php.net/manual/en/domnode.insertbefore.php
 * @param DOMNode $newNode The node to insert
 * @param DOMNode $refNode The reference node
 * @param string $insertMode How to insert the node ? After ? Before ? Inside ? By default it's inside
 */
	public function insertNode($newNode, $refNode, $insertMode='inside') {
		if($insertMode == 'inside') {
				$refNode->appendChild($newNode);
		} else if($insertMode == 'before') {
				$refNode->parentNode->insertBefore($newNode, $refNode);
		} else if($insertMode == 'after') {
				if($refNode->nextSibling) {
						$refNode->parentNode->insertBefore($newNode, $refNode->nextSibling);
				} else {
						$refNode->parentNode->appendChild($newNode);
				}     
		}
	}
}